#ifndef __PLATFORM_OROLE_H__
#define __PLATFORM_OROLE_H__

#include "physics/oBody.h"
#include "platform/oUnitDef.h"
#include "platform/oProperty.h"

class oModel;
class oSensor;

namespace platform
{
	class oAction;
	class oBulletDef;
	class oUnitDef;
	class oProperty;
	class oInstinct;
	class oAILeaf;

	class oDLL oUnit: public oBody
	{
		typedef unordered_map<int, oAction*> oActionMap;
		typedef hash_strmap<oProperty*> oPropertyMap;
	public:
		virtual ~oUnit();
		//Class properties
		PROPERTY(oModel*, _model, Model);
		PROPERTY(float, _detectDistance, DetectDistance);
		PROPERTY_REF(CCSize, _attackRange, AttackRange);
		PROPERTY_BOOL(_isFaceRight, FaceRight);
		PROPERTY_READONLY(oSensor*, GroundSensor);
		PROPERTY_READONLY(oSensor*, DetectSensor);
		PROPERTY_READONLY(oSensor*, AttackSensor);
		PROPERTY_READONLY(oUnitDef*, UnitDef);
		PROPERTY_READONLY(oAction*, CurrentAction);
		PROPERTY(oBulletDef*, _bulletDef, BulletDef);
		PROPERTY_READONLY(float, Width);
		PROPERTY_READONLY(float, Height);
		//
		virtual void setGroup( oGroup* group );
		virtual void update( ccTime dt );
		//Actions
		oAction* attachAction(int id);
		void attachAction(oAction* action);
		oAction* getAction(int id) const;
		bool doIt(int id);
		//
		bool isOnSurface() const;
		void onActionEnd(oAction* action);
		static oUnit* node(oWorld* world, oUnitDef* unitDef);
		//Named properties
		class oDLL oPropertySet
		{
		public:
			~oPropertySet();
			oProperty& operator[](const string& name);
			const oProperty& operator[](const string& name) const;
			oProperty* get(const string& name) const;
			void remove(const string& name);
			void clear();
		private:
			void setOwner(oUnit* owner);
			oUnit* _owner;
			oPropertyMap _items;
			friend class oUnit;
		} properties;
		//Dynamic properties
		float sensity;
		float move;
		float moveSpeed;
		float jump;
		oProperty hp;
		float maxHp;
		float attackBase;
		float attackBonus;
		float attackFactor;
		float attackSpeed;
		CCPoint attackPower;
		oAttackType attackType;
		oAttackTarget attackTarget;
		oTargetAllow targetAllow;
		oDamageType damageType;
		oDefenceType defenceType;
		//Instinct
		class oDLL oInstinctSet
		{
		public:
			void add(oInstinct* instinct);
			void remove(oInstinct* instinct);
			void reinstall();
			void clear();
		private:
			void setOwner(oUnit* owner);
			oUnit* _owner;
			vector<oInstinct*> _instincts;
			friend class oUnit;
		} instincts;
		//Conditioned Reflex
		PROPERTY(oAILeaf*, _reflexArc, ReflexArc);
	protected:
		oUnit(oWorld* world, oUnitDef* unitDef);
	private:
		oUnitDef* _unitDef;
		CCSize _size;
		oSensor* _groundSensor;
		oSensor* _detectSensor;
		oSensor* _attackSensor;
		oAction* _currentAction;
		oActionMap _actions;
	};
}

#endif